using System;
using System.Collections.Generic;
using UnityEngine;

public static class BCWStorage
{
	private class StorageUnit
	{
		public bool changed;

		private int _offset;

		public object _value;

		private Type _type;

		public object value
		{
			get
			{
				if (_type == typeof(int))
				{
					return (int)_value - _offset;
				}
				if (_type == typeof(float))
				{
					return (float)_value - (float)_offset;
				}
				if (_type == typeof(string))
				{
					return Encrypt((string)_value, _offset);
				}
				return _value;
			}
			set
			{
				_offset = UnityEngine.Random.Range(-1000, 1000);
				if (_type == typeof(int))
				{
					_value = (int)value + _offset;
				}
				else if (_type == typeof(float))
				{
					_value = (float)value + (float)_offset;
				}
				else if (_type == typeof(string))
				{
					_value = Encrypt((string)value, _offset);
				}
				else
				{
					_value = value;
				}
			}
		}

		public Type Type
		{
			get
			{
				return _type;
			}
		}

		public StorageUnit(object val, Type valType)
		{
			_type = valType;
			value = val;
		}

		private static string Encrypt(string message, int key)
		{
			string text = string.Empty;
			for (int i = 0; i < message.Length; i++)
			{
				text += (char)(message[i] ^ key);
			}
			return text;
		}
	}

	private static Dictionary<string, StorageUnit> _storage = new Dictionary<string, StorageUnit>();

	private static Dictionary<Type, Func<string, object>> _stringToType = new Dictionary<Type, Func<string, object>>
	{
		{
			typeof(int),
			(string s) => StringToInt(s)
		},
		{
			typeof(float),
			(string s) => StringToFloat(s)
		},
		{
			typeof(bool),
			(string s) => StringToBool(s)
		},
		{
			typeof(string),
			(string s) => s
		},
		{
			typeof(Vector3),
			(string s) => StringToVector3(s)
		},
		{
			typeof(Quaternion),
			(string s) => StringToQuaternion(s)
		}
	};

	private static Dictionary<Type, Func<object, string>> _typeToString = new Dictionary<Type, Func<object, string>>
	{
		{
			typeof(int),
			(object o) => ((int)o).ToString()
		},
		{
			typeof(float),
			(object o) => ((float)o).ToString()
		},
		{
			typeof(bool),
			(object o) => (!(bool)o) ? "0" : "1"
		},
		{
			typeof(string),
			(object o) => (string)o
		},
		{
			typeof(Vector3),
			(object o) => ((Vector3)o).x + "&" + ((Vector3)o).y + "&" + ((Vector3)o).z
		},
		{
			typeof(Quaternion),
			(object o) => ((Quaternion)o).x + "&" + ((Quaternion)o).y + "&" + ((Quaternion)o).z + "&" + ((Quaternion)o).w
		}
	};

	public static List<string> keysContains = new List<string>();

	public static int lengthStorage
	{
		get
		{
			return _storage.Count;
		}
	}

	public static bool Set<T>(string key, T value, bool immediatelySave = false)
	{
		if (_stringToType.ContainsKey(typeof(T)))
		{
			if (!_storage.ContainsKey(key))
			{
				_storage.Add(key, new StorageUnit(LoadFromDrive<T>(key), typeof(T)));
			}
			_storage[key].value = value;
			_storage[key].changed = true;
			if (immediatelySave)
			{
				Save(key, true);
			}
			return true;
		}
		BCWDebug.LogError("Try to set unsuported type");
		return false;
	}

	public static T Get<T>(string key)
	{
		if (_stringToType.ContainsKey(typeof(T)))
		{
			if (!_storage.ContainsKey(key))
			{
				if (!CryptoPlayerPrefs.HasKey(key))
				{
					return (T)new StorageUnit(LoadFromDrive<T>(key), typeof(T)).value;
				}
				_storage.Add(key, new StorageUnit(LoadFromDrive<T>(key), typeof(T)));
			}
			return (T)_storage[key].value;
		}
		BCWDebug.LogError("Try to get unsuported type");
		return default(T);
	}

	public static void SaveAll(bool needSaveByFrame = false)
	{
		if (needSaveByFrame)
		{
			string[] array = new string[_storage.Keys.Count];
			_storage.Keys.CopyTo(array, 0);
			keysContains.Clear();
			keysContains.AddRange(array);
			keysContains.RemoveAll((string x) => !_storage[x].changed);
			if (SaveBCWStorage.instance == null)
			{
				SaveBCWStorage.Init();
			}
			BCWDebug.Log("keysContains: " + keysContains.Count, "BCWStorage");
			SaveBCWStorage.instance.StartSaveKeys(keysContains.Count);
		}
		else
		{
			foreach (string key in _storage.Keys)
			{
				if (_storage[key].changed && _typeToString.ContainsKey(_storage[key].Type))
				{
					Save(key, false);
				}
			}
		}
		PlayerPrefs.Save();
	}

	public static void SaveAllByFrame(int i)
	{
		if (i < keysContains.Count && _storage[keysContains[i]].changed && _typeToString.ContainsKey(_storage[keysContains[i]].Type))
		{
			Save(keysContains[i], false);
			BCWDebug.Log("SaveAllByFrame: " + keysContains[i], "BCWStorage");
		}
	}

	public static void Save(string key, bool withPPSave)
	{
		if (_storage[key].Type == typeof(int))
		{
			CryptoPlayerPrefs.SetInt(key, (int)_storage[key].value);
		}
		else if (_storage[key].Type == typeof(bool))
		{
			CryptoPlayerPrefs.SetInt(key, int.Parse(_typeToString[_storage[key].Type](_storage[key].value)));
		}
		else
		{
			CryptoPlayerPrefs.SetString(key, _typeToString[_storage[key].Type](_storage[key].value));
		}
		_storage[key].changed = false;
		if (withPPSave)
		{
			PlayerPrefs.Save();
		}
	}

	public static void Delete(string key)
	{
		if (_storage.ContainsKey(key))
		{
			_storage.Remove(key);
		}
		CryptoPlayerPrefs.DeleteKey(key);
	}

	public static void PrintDictionary()
	{
		string text = string.Empty;
		foreach (string key in _storage.Keys)
		{
			string text2 = text;
			text = text2 + key + "  " + _storage[key]._value.ToString() + "\n";
		}
		Debug.Log(text);
	}

	public static void PrintMyDictionary()
	{
		foreach (string key in _storage.Keys)
		{
			Debug.LogError(key + " " + _storage[key]._value.ToString());
		}
	}

	private static object LoadFromDrive<T>(string key)
	{
		if (_stringToType.ContainsKey(typeof(T)))
		{
			string empty = string.Empty;
			empty = ((typeof(T) == typeof(int)) ? CryptoPlayerPrefs.GetInt(key).ToString() : ((typeof(T) != typeof(bool)) ? CryptoPlayerPrefs.GetString(key) : CryptoPlayerPrefs.GetInt(key).ToString()));
			return _stringToType[typeof(T)](empty);
		}
		return default(T);
	}

	private static int StringToInt(string value)
	{
		int result;
		if (int.TryParse(value, out result))
		{
			return result;
		}
		return 0;
	}

	private static float StringToFloat(string value)
	{
		float result;
		if (float.TryParse(value, out result))
		{
			return result;
		}
		return 0f;
	}

	private static bool StringToBool(string value)
	{
		int result;
		if (int.TryParse(value, out result))
		{
			if (result == 1)
			{
				return true;
			}
			return false;
		}
		return false;
	}

	private static Vector3 StringToVector3(string value)
	{
		string[] array = value.Split("&"[0]);
		float result;
		float result2;
		float result3;
		if (float.TryParse(array[0], out result) && float.TryParse(array[1], out result2) && float.TryParse(array[2], out result3))
		{
			return new Vector3(result, result2, result3);
		}
		return Vector3.zero;
	}

	private static Quaternion StringToQuaternion(string value)
	{
		string[] array = value.Split("&"[0]);
		float result;
		float result2;
		float result3;
		float result4;
		if (float.TryParse(array[0], out result) && float.TryParse(array[1], out result2) && float.TryParse(array[2], out result3) && float.TryParse(array[3], out result4))
		{
			return new Quaternion(result, result2, result3, result4);
		}
		return Quaternion.identity;
	}
}
